package my.edu.security.oauth;

import cn.hutool.core.convert.NumberWithFormat;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import my.edu.common.constant.MessageConstant;
import my.edu.common.exception.TokenInvalidException;
import my.edu.model.User.service.IUserService;
import my.edu.model.User.entity.User;
import my.edu.common.exception.ErrorCode;
import my.edu.security.shiroservice.ShiroService;
import my.edu.security.userEntity.UserDetail;
import my.edu.security.userEntity.UserToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.Set;

@Component
@AllArgsConstructor
public class Oauth2Realm extends AuthorizingRealm {

    @Resource
    @Qualifier("shiroServiceImpl")
    private  ShiroService shiroService;

    @Resource
   private IUserService userService;

    public Oauth2Realm() {
        // 禁用认证缓存
        setAuthenticationCachingEnabled(false);
        // 禁用授权缓存
        setAuthorizationCachingEnabled(false);
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof Oauth2Token;
    }

    /**
     * 授权(验证权限时调用)
     * 当controller上有权限注解的时候调用注解
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        UserDetail user = (UserDetail) principals.getPrimaryPrincipal();

        //权限列表
        Set<String> permsSet = shiroService.getUserPermissions(user);
        //角色列表
        Set<String> roleSet = shiroService.getUserRoles(user);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permsSet);
        info.setRoles(roleSet);
        return info;
    }

    /**
     * filter的输出之一就是封装好的token，并当做这里的输入
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String accessToken = (String) token.getPrincipal();

        JWT jwt = JWTUtil.parseToken(accessToken);
        Object userId1 = jwt.getPayload("userId");
        NumberWithFormat userId = (NumberWithFormat) userId1;
//        //根据accessToken，查询用户信息
         UserToken tokenEntity = shiroService.getToken(userId.longValue());
//        //token失效
        if (tokenEntity == null|| !tokenEntity.getToken().equals(accessToken) || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()) {
            throw new TokenInvalidException(MessageConstant.TOKEN_INVALID );
        }
        //查询用户信息
        User userEntity = userService.getById(tokenEntity.getUserId());
        //转换成UserDetail对象
        UserDetail userDetail = new UserDetail();
        BeanUtils.copyProperties(userEntity, userDetail);

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDetail, accessToken, getName());
        return info;
    }


}